﻿using System;
using System.Globalization;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using SpreadsheetGear;
using ZedGraph;
using SoftwareConsulting.BI11.Studio.Core.Project.Metadata;
using SoftwareConsulting.BI11.Studio.InternalServices;

namespace SoftwareConsulting.BI11.Studio.UI.ProjectExplorer
{
    /// <summary>
    /// Диалог моделирования
    /// </summary>
    public partial class ModelingDialog : RestorableForm
    {
        //bbb private string _cubeName; //имя анализуемого куба
        //bbb private CalendarDynamics _calendarDynamics; //динамика анализируемого календарного измерения
        //bbb private string _calendarDimensionName; //имя анализируемого календарного измерения
        private string _rowName; //имя исходного ряда
        //bbb private List<string> _rowsCaptions; //названия анализируемых рядов
        //bbb private TableLayoutPanel _valuesRows; //анализируемые ряды
        //BBB private AnalysisMethods _method; //метод анализа
        //BBB private SmoothingMethods _smoothing; //метод сглаживания
        //bbb private MissingDataMethods _missing; //метод заполнения пропусков
        //BBB private ApproximateFucntions _approx; //приближающая функция
        //bbb private bool _blockAnalizing; //флаг блокировки анализа
        private PointPairList graphPoints_SourceRow; //точки на графике для исходного ряда
        private PointPairList graphPoints_NoMissingRow; //точки на графике для исходного ряда избавленного от пропусков
        private PointPairList graphPoints_ModelRow; //точки на графике для моделируемого ряда
        private PointPairList graphPoints_ForecastRow; //точки на графике для прогнозируемого ряда

        /// <summary>
        /// Строит график
        /// </summary>
        private void DrawGraph()
        {
            /*bbb GraphPane myPane = ResultsGraph.GraphPane;             
            myPane.IsIgnoreMissing = false;
            myPane.Title.Text = _cubeName;
            myPane.XAxis.Title.Text = _calendarDimensionName;
            myPane.YAxis.Title.Text = _rowName;

            // Show the x axis grid
            myPane.XAxis.MajorGrid.IsVisible = true;

            // Make the Y axis scale red
            myPane.YAxis.Scale.FontSpec.FontColor = Color.Red;
            myPane.YAxis.Title.FontSpec.FontColor = Color.Red;
            // Align the Y axis labels so they are flush to the axis
            myPane.YAxis.Scale.Align = AlignP.Inside;
            myPane.XAxis.Type = AxisType.Text;
            myPane.XAxis.Scale.Min = 0;
            myPane.XAxis.Scale.MinorStep = 1;
            myPane.XAxis.Scale.MajorStep = 1;            

            // Fill the axis background with a gradient
            myPane.Chart.Fill = new Fill(Color.White, Color.LightGray, 45.0f);

            // Enable scrollbars if needed
            ResultsGraph.IsShowHScrollBar = true;
            ResultsGraph.IsShowVScrollBar = true;
            ResultsGraph.IsAutoScrollRange = true;            

            // OPTIONAL: Show tooltips when the mouse hovers over a point
            ResultsGraph.IsShowPointValues = true;

            //рисуем
            myPane.CurveList.Clear();
            LineItem myCurve_source = myPane.AddCurve(ResultsGrid.Columns[1].HeaderText,
                    graphPoints_SourceRow, GeneralMethods.GetColorByIndex(0), GeneralMethods.GetGraphSymbolByIndex(0));              
            myCurve_source.Symbol.Fill = new Fill(Color.White);
            LineItem myCurve_nomissing = myPane.AddCurve(ResultsGrid.Columns[2].HeaderText,
                    graphPoints_NoMissingRow, GeneralMethods.GetColorByIndex(1), GeneralMethods.GetGraphSymbolByIndex(1));
            myCurve_nomissing.Symbol.Fill = new Fill(Color.White);
            LineItem myCurve_model = myPane.AddCurve(ResultsGrid.Columns[3].HeaderText,
                    graphPoints_ModelRow, GeneralMethods.GetColorByIndex(2), GeneralMethods.GetGraphSymbolByIndex(2));
            myCurve_model.Symbol.Fill = new Fill(Color.White);
            LineItem myCurve_forecast = myPane.AddCurve(ResultsGrid.Columns[4].HeaderText,
                    graphPoints_ForecastRow, GeneralMethods.GetColorByIndex(3), GeneralMethods.GetGraphSymbolByIndex(3));            
            myCurve_forecast.Symbol.Fill = new Fill(Color.White);

            // Make sure the Graph gets redrawn
            ResultsGraph.AxisChange();
            ResultsGraph.Invalidate();
             * */
        }

        /// <summary>
        /// Проводит анализ
        /// </summary>
        private void Analize()
        {
            //bbb if (!_blockAnalizing)
            {
                CultureInfo ci = CultureInfo.CurrentCulture;
                int rowIndex = RowsCombo.SelectedIndex + 1;
                //bbb int j = 0;
                graphPoints_SourceRow = new PointPairList();                
                graphPoints_NoMissingRow = new PointPairList();
                graphPoints_ModelRow = new PointPairList();
                graphPoints_ForecastRow = new PointPairList();
                //bbb int firstvalueable = -1;
                ResultsGrid.Rows.Clear();
                /*BBB while (j < _valuesRows.ColumnCount)
                {
                    Control cell = _valuesRows.GetControlFromPosition(j, rowIndex) as Control;
                    while (cell is Panel) //угловая ячейка
                    {
                        rowIndex++;
                        cell = _valuesRows.GetControlFromPosition(j, rowIndex) as Control;
                    }
                    if (cell.Tag == null)                    
                    {                    
                        //значит ячейка данных
                        if (firstvalueable == -1)
                        {
                            firstvalueable = j;
                        }
                        object sourcerow_value = cell.Text;
                        sourcerow_value = (sourcerow_value as string).Trim() == string.Empty ? double.MaxValue : double.Parse(sourcerow_value as string, ci);
                        graphPoints_SourceRow.Add(0, (double)sourcerow_value);
                        object nomissingrow_value = sourcerow_value;
                        if (sourcerow_value.Equals(double.MaxValue))
                        {
                            switch (_missing)
                            {
                                case MissingDataMethods.Average:
                                    object haveleft = null;
                                    for (int k = j - 1 - firstvalueable; k >= 0; k--)
                                    {
                                        if (graphPoints_SourceRow[k].Y != double.MaxValue)
                                        {
                                            haveleft = graphPoints_SourceRow[k].Y;
                                            break;
                                        }
                                    }
                                    object haveright = null;
                                    for (int k = j + 1 - firstvalueable; k < _valuesRows.ColumnCount - firstvalueable; k++)
                                    {
                                        string vv = (_valuesRows.GetControlFromPosition(k + firstvalueable, rowIndex) as TextBox).Text;
                                        if (vv.Trim() != string.Empty)
                                        {
                                            haveright = double.Parse(vv, ci);
                                            break;
                                        }
                                    }
                                    if ((haveleft != null) && (haveright != null))
                                    {
                                        nomissingrow_value = ((double)haveleft + (double)haveright) / 2;
                                    }
                                    else
                                    {
                                        if ((haveleft == null) && (haveright != null))
                                        {
                                            nomissingrow_value = haveright;
                                        }
                                        if ((haveleft != null) && (haveright == null))
                                        {
                                            nomissingrow_value = haveleft;
                                        }
                                        if ((haveleft == null) && (haveright == null))
                                        {
                                            nomissingrow_value = double.MaxValue;
                                        }
                                    }
                                    break;
                            }
                        }
                        if (!double.MaxValue.Equals(nomissingrow_value))
                        {
                            nomissingrow_value = double.Parse(nomissingrow_value.ToString(), ci);
                        }
                        graphPoints_NoMissingRow.Add(0, (double)nomissingrow_value);
                        object modelrow_value = double.MaxValue;
                        /*BBB switch (_smoothing)
                        {
                            case SmoothingMethods.MovingAverage_Average:
                                if (j - firstvalueable >= (WindowWidthEdit.Value - 1))
                                {
                                    double sum = 0;
                                    for (int k = j - (int)WindowWidthEdit.Value + 1 - firstvalueable; k <= j - firstvalueable; k++)
                                    {
                                        sum += graphPoints_NoMissingRow[k].Y;
                                    }
                                    modelrow_value = sum;
                                }
                                break;
                            case SmoothingMethods.MovingAverage_Median:
                                if (j - firstvalueable >= (WindowWidthEdit.Value - 1))
                                {
                                    List<double> winvals = new List<double>();
                                    for (int kk = j - (int)WindowWidthEdit.Value + 1 - firstvalueable; kk <= j - firstvalueable; kk++)
                                    {
                                        winvals.Add(graphPoints_NoMissingRow[kk].Y);
                                    }
                                    winvals.Sort();
                                    if (winvals.Count % 2 != 0)
                                    {
                                        //нечетное число значений
                                        int index = winvals.Count / 2 + 1;
                                        index = (index <= winvals.Count - 1) ? index : winvals.Count - 1;
                                        modelrow_value = winvals[index];
                                    }
                                    else
                                    {
                                        modelrow_value = (winvals[winvals.Count / 2 - 1] + winvals[winvals.Count / 2]) / 2;
                                    }
                                }
                                break;
                        }*/
                /*bbb graphPoints_ModelRow.Add(0, (double)modelrow_value);
                if (j < _valuesRows.ColumnCount - 1)
                {
                    graphPoints_ForecastRow.Add(0, double.MaxValue);
                }
                else
                {
                    graphPoints_ForecastRow.Add(0, (double)modelrow_value);
                }                        
                ResultsGrid.Rows.Add((_valuesRows.GetControlFromPosition(j, 0) as System.Windows.Forms.Label).Text, sourcerow_value.Equals(double.MaxValue) ? string.Empty : sourcerow_value.ToString(), nomissingrow_value.ToString(), modelrow_value.Equals(double.MaxValue) ? string.Empty : modelrow_value.ToString(), string.Empty);
            }
            j++;
        }*/
                /*BBB switch (_approx)
                {
                    case ApproximateFucntions.Linear:
                        double x1 = ResultsGrid.Rows.Count - 1 - (int)WindowWidthEdit.Value + 1;
                        double x2 = ResultsGrid.Rows.Count - 1;
                        double y1 = double.Parse(ResultsGrid.Rows[int.Parse(x1.ToString())].Cells[3].Value.ToString(), ci);
                        double y2 = double.Parse(ResultsGrid.Rows[int.Parse(x2.ToString())].Cells[3].Value.ToString(), ci);
                        double otn = (y2 - y1) / (x2 - x1);
                        for (int i = 0; i < (int)ForecastLengthEdit.Value; i++)
                        {
                            double fore = y1 - otn * x1 + otn * ResultsGrid.Rows.Count;
                            graphPoints_ForecastRow.Add(0, fore);
                            string datestring = ResultsGrid.Rows[ResultsGrid.Rows.Count - 1].Cells[0].Value.ToString();
                            switch (_calendarDynamics)
                            {
                                case CalendarDynamics.Years:
                                    datestring = (int.Parse(datestring) + 1).ToString();
                                    break;
                                case CalendarDynamics.YearsMonths:
                                    //TODOif (datestring is int)
                                    {
                                        //заголовок периода
                                        //TODO че-то надо делать
                                    }
                                    //TODOelse
                                    {
                                        datestring = DateTime.Parse(datestring, ci).AddMonths(1).ToString("yyyy MMM");
                                    }
                                    break;
                                case CalendarDynamics.MonthsDays:
                                    datestring = DateTime.Parse(datestring, ci).AddDays(1).ToString("m");
                                    break;
                            }
                            ResultsGrid.Rows.Add(datestring, string.Empty, string.Empty, string.Empty, fore.ToString());
                        }
                        break;
                }*/
                DrawGraph();
            }
        }

        /// <summary>
        /// Подготавливает диалог
        /// </summary>
        private void Initialize()
        {
            /*BBB _blockAnalizing = true;
            ComboBox.ObjectCollection items = MethodCombo.Items;
            items.Clear();
            for (int i = 0; i < 1; i++)
            {
                items.Add(BIGeneralMethods.GetAnalysisMethodNameByIndex(i));
            }
            MethodCombo.SelectedIndex = (int)_method;
            items = SmoothingMethodCombo.Items;
            items.Clear();
            for (int i = 0; i < 2; i++)
            {
                items.Add(BIGeneralMethods.GetSmoothingMethodNameByIndex(i));                
            }            
            SmoothingMethodCombo.SelectedIndex = (int)_smoothing;
            items = MissingDataMethodCombo.Items;
            items.Clear();
            for (int i = 0; i < 1; i++)
            {
                items.Add(BIGeneralMethods.GetMissingDataMethodNameByIndex(i));
            }            
            MissingDataMethodCombo.SelectedIndex = (int)_missing;
            items = ApproxFuncCombo.Items;
            items.Clear();
            for (int i = 0; i < 1; i++)
            {
                items.Add(BIGeneralMethods.GetApproximateFunctionNameByIndex(i));
            }
            ApproxFuncCombo.SelectedIndex = (int)_approx;
            _rowsCaptions = new List<string>();
            for (int i = 1; i < _valuesRows.RowCount; i++)
            {
                int j = 0;
                string newcap = string.Empty;
                Control vv = _valuesRows.GetControlFromPosition(j, i) as Control;
                while ((vv != null) && (vv.Tag != null))                
                {
                    //заголовочная ячейка
                    newcap = newcap + vv.Text + " - ";
                    j++;
                    vv = _valuesRows.GetControlFromPosition(j, i) as Control;
                }
                newcap = newcap.Substring(0, newcap.Length - 3);
                _rowsCaptions.Add(newcap);
            }
            items = RowsCombo.Items;
            items.Clear();
            for (int i = 0; i < _rowsCaptions.Count; i++)
            {
                items.Add(_rowsCaptions[i]);
            }            
            RowsCombo.SelectedIndex = 0;            
            _blockAnalizing = false;
            Analize();*/
        }

        /// <summary>
        /// Строит отчет по результатам анализа
        /// </summary>
        private void MakeReport()
        {
            GeneralMethods.UnderConstruction();
        }

        /*BBB /// <summary>
        /// Конструктор формы
        /// </summary>        
        public ModellingDialog(AnalysisMethods startmethod, string newcubename, string newcalendardimname, TableLayoutPanel valuesTable, CalendarDynamics newcaldyn)
        {
            _calendarDynamics = newcaldyn;
            _valuesRows = valuesTable;
            _calendarDimensionName = newcalendardimname;
            _cubeName = newcubename;
            _method = startmethod;
            InitializeComponent();
        }*/

        private void CloseButton_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void AnalysysDialog_Load(object sender, EventArgs e)
        {
            Initialize();
        }

        private void RowsCombo_SelectedIndexChanged(object sender, EventArgs e)
        {
            _rowName = RowsCombo.Text;
            Analize();
        }

        private void MethodCombo_SelectedIndexChanged(object sender, EventArgs e)
        {
            /*BBB switch (_method)
            {
                case AnalysisMethods.Trend:
                    _smoothing = SmoothingMethods.MovingAverage_Average;
                    _missing = MissingDataMethods.Average;
                    _approx = ApproximateFucntions.Linear;
                    break;
            }
            Analize();*/
        }

        private void WindowWidthEdit_ValueChanged(object sender, EventArgs e)
        {
            Analize();
        }

        private void SmoothingMethodCombo_SelectedIndexChanged(object sender, EventArgs e)
        {
/*BBB             _smoothing = (SmoothingMethods)SmoothingMethodCombo.SelectedIndex;
            Analize();*/
        }

        private void ReportButton_Click(object sender, EventArgs e)
        {
            MakeReport();
        }

        private void MissingDataMethodCombo_SelectedIndexChanged(object sender, EventArgs e)
        {
            Analize();
        }

        private void ApproxFuncCombo_SelectedIndexChanged(object sender, EventArgs e)
        {
            Analize();
        }

        private void ForecastLengthEdit_ValueChanged(object sender, EventArgs e)
        {
            Analize();
        }  
    }
}
